package fun.abbas.demo240621.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.Xfermode;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

public class WeightView2 extends View {

    private Bitmap shaderBimap;
    private Canvas shaderCanvas;

    private int width;
    private int height;

    private LinearGradient shaderGradient;
    private final Paint shaderPaint = new Paint();
    private final Paint linePaint = new Paint();
    private final Paint pointOuterPaint = new Paint();
    private final Paint pointInnerPaint = new Paint();
    private final Paint clear = new Paint();
    private final Path shaderPath = new Path();

    private final List<Integer> data = new ArrayList<>();

    public WeightView2(Context context) {
        super(context);
        init();
    }

    public WeightView2(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WeightView2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public WeightView2(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init() {

        shaderPaint.setStyle(Paint.Style.FILL);
        linePaint.setColor(Color.parseColor("#8195EE"));
        linePaint.setStrokeWidth(5f);
        pointOuterPaint.setColor(Color.parseColor("#8195EE"));
        pointOuterPaint.setStrokeWidth(10f);
        pointInnerPaint.setColor(Color.WHITE);
        pointInnerPaint.setStrokeWidth(5f);
        clear.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    }

    private void initCanvas() {
        if (shaderBimap == null) {
            shaderBimap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        }
        if (shaderCanvas == null) {
            shaderCanvas = new Canvas(shaderBimap);
        }

    }

    private int[] colors = new int[]{Color.parseColor("#8195EE"), Color.parseColor("#8195EE")};

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        widthSpace = width / (data.size() - 1);
        heightSpaces = height / ((max - min) * 3);
        shaderGradient = new LinearGradient(0, 0, 0, height, colors, null, Shader.TileMode.CLAMP);
        shaderPaint.setShader(shaderGradient);
    }

    private int widthSpace;
    private int heightSpaces;

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        initCanvas();
        shaderCanvas.drawPaint(clear);
        shaderPath.reset();
        shaderPath.moveTo(0, height);
        data2Point();
        for (int i = 0; i < pointers.length / 2; i += 2) {
            shaderPath.lineTo(pointers[i], pointers[i + 1]);
        }
        shaderPath.moveTo(width, height);
        shaderPath.close();
        shaderCanvas.drawPath(shaderPath, shaderPaint);
        shaderCanvas.drawLines(pointers, linePaint);
        for (int i = 0; i < pointers.length / 2; i += 2) {
            shaderCanvas.drawCircle(pointers[i], pointers[i + 1],10,pointOuterPaint);
            shaderCanvas.drawCircle(pointers[i], pointers[i + 1],5,pointInnerPaint);
        }
        canvas.drawBitmap(shaderBimap,0,0,null);
    }

    private float[] pointers;

    private void data2Point() {
        pointers = new float[data.size() * 2];
        for (int i = 0; i < data.size(); i++) {
            Integer j = data.get(i);
            float x = i * widthSpace;
            int y = (max - j) * heightSpaces;
            pointers[i * 2] = x;
            pointers[i * 2 + 1] = y;
        }
    }

    private int max;
    private int min;

    public void setData(List<Integer> data) {
        this.data.clear();
        this.data.addAll(data);
        data.stream().mapToInt(i -> i)
                .min().ifPresent(i -> min = i);
        data.stream().mapToInt(i -> i)
                .max().ifPresent(i -> max = i);
        invalidate();
    }

}
